/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cxhd.dc.websocket;

import com.cxhd.dc.DataConfig;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.http.HttpRequestEncoder;
import org.jboss.netty.handler.codec.http.HttpResponseDecoder;
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion;

/**
 *
 * @author Administrator
 */
public class ConnectServer {

    static final String URL = System.getProperty("url", "ws://transfer.tronsystem.com:19090/websocket/" + DataConfig.getInstance().getLocalhostSN()+"&"+DataConfig.version);
  //static final String URL = System.getProperty("url", "ws://localhost:19090/websocket/" + DataConfig.getInstance().getLocalhostSN()+"&"+DataConfig.version);

    private Channel ch = null;
    private ClientBootstrap bootstrap;
    private boolean close = true;
    private boolean start = true;
    private static ConnectServer con;

    public void connect() {
        bootstrap
                = new ClientBootstrap(
                        new NioClientSocketChannelFactory(
                                Executors.newCachedThreadPool(),
                                Executors.newCachedThreadPool()));
        try {
            URI uri = new URI(URL);
            Map<String, String> customHeaders = new HashMap<String, String>();
            customHeaders.put("MyHeader", "MyValue");

            final WebSocketClientHandshaker handshaker
                    = new WebSocketClientHandshakerFactory().newHandshaker(
                            uri, WebSocketVersion.V13, null, false, customHeaders);

            bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
                public ChannelPipeline getPipeline() {
                    ChannelPipeline pipeline = Channels.pipeline();

                    pipeline.addLast("decoder", new HttpResponseDecoder());
                    pipeline.addLast("encoder", new HttpRequestEncoder());
                    pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
                    return pipeline;
                }
            });

            // Connect.
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(uri.getHost(), uri.getPort()));

            ch = future.sync().getChannel();

            handshaker.handshake(ch).sync();

        } catch (Exception ex) {

            ex.printStackTrace();

        }
    }

    public void reConnect() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (close) {
                    try {
                        if (!start) {
                            Thread.sleep(3000);
                        }
                        start = false;

                        if (ch == null || !ch.isConnected()) {

                            if (ch != null) {
                                ch.close();
                            }
                            if (bootstrap != null) {
                                bootstrap.releaseExternalResources();
                            }
                            //System.out.println("开始链接");
                            connect();
                            // System.out.println("开始链接22222");

                        } else {
                            //System.out.println(ch.isConnected());
                            if (ch.isConnected()) {
                                ch.write(new PingWebSocketFrame());
                            }
                        }
                    } catch (Exception ex) {
                        // ex.printStackTrace();
                    }
                }

            }
        }).start();

    }

    public void sendMessage(String message) {
        if (ch != null) {
            ch.write(new TextWebSocketFrame(message));
        }
    }

    public void close() {

        if (ch != null) {
            close = false;
            ch.close();
        }
        if (bootstrap != null) {
            bootstrap.releaseExternalResources();
        }
    }

    public void getData() {

        ExecutorService executor = Executors.newSingleThreadExecutor();
        FutureTask<String> future
                = new FutureTask<String>(new Callable<String>() {//使用Callable接口作为构造参数   
                    public String call() {
                        return null;
                        //真正的任务在这里执行，这里的返回值类型为String，可以为任意类型   
                    }
                });
        executor.execute(future);
    }

    public static ConnectServer getIntance() {
        if (con == null) {
            con = new ConnectServer();
        }
        return con;
    }

    public static void main(String[] args) {
        ConnectServer con = new ConnectServer();
        con.reConnect();
    }

}
